﻿#pragma comment(lib,"pthreadVC2.lib")
#define HAVE_STRUCT_TIMESPEC
#include <iostream>
#include<random>
#include<iomanip>
#include<windows.h>
#include<pthread.h>
#include <stdlib.h>
#include<stdio.h>
#include<semaphore.h>
using namespace std;
const int N = 1024;

const int THREAD_NUM = 6; // 线程数量
pthread_t threads[THREAD_NUM]; // 线程数组

float A[N][N];

struct threadParam_t {
    int t_id;//线程id
};

//信号量定义
sem_t sem_main;
sem_t sem_workerstart[THREAD_NUM]; // 每个线程有自己专属的信号量
sem_t sem_workerend[THREAD_NUM];

void* threadFunc(void* param) {
    threadParam_t* p = (threadParam_t*)param;
    int t_id = p->t_id;

    for (int k=0; k < N; k++)
    {
        sem_wait(&sem_workerstart[t_id]); // 阻塞，等待主线完成除法操作（操作自己专属的信号量）
        //循环划分任务
        for (int i = k + 1 + t_id; i < N; i += THREAD_NUM)
        {
            //消去
            for (int j = k + 1; j < N; j++) 
            {
                A[i][j] = A[i][j] -A[i][k] * A[k][j];
            }
            A[i][k] = 0.0;
        }
        sem_post(&sem_main); // 唤醒主线程
        sem_wait(&sem_workerend[t_id]); //阻塞，等待主线程唤醒进入下一轮
    }
    pthread_exit(NULL);

}


void reset()
{
    A[0][0] = 0;
    for (int i = 0; i < N; i++)
    {
        A[i][i] = 1.0;
        for (int j = i + 1; j < N; j++)
        {
            A[i][j] = rand();//上三角赋值
        }
    }

    for (int k = 0; k < N; k++)
    {

        for (int i = k + 1; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                A[i][j] += A[k][j];//将上一行的数加到其下的每一行

            }
        }

    }
}

int main(int argc, char* argv[])
{
    reset();

    sem_init(&sem_main, 0, 0);
    for (int i = 0; i < THREAD_NUM; i++)
    {
        sem_init(&sem_workerstart[i], 0, 0);
        sem_init(&sem_workerend[i], 0, 0);
    }

   
    long long head, tail, freq; // timers
    // similar to CLOCKS_PER_SEC
    QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
    // start time
    QueryPerformanceCounter((LARGE_INTEGER*)&head);

    pthread_t handles[THREAD_NUM];// 创建对应的 Handle
    threadParam_t param[THREAD_NUM];// 创建对应的线程数据结构
    for (int t_id = 0; t_id < THREAD_NUM; t_id++)
    {
        param[t_id].t_id = t_id;
        pthread_create(&handles[t_id], NULL, threadFunc, (void*)&param[t_id]);
    }

    for (int k = 0; k < N; k++)
    {
        for (int j = k + 1; j < N; j++)
        {
            if (A[k][k] != 0)
                A[k][j] = A[k][j] / A[k][k];
        }
        A[k][k] = 1.0;
        //开始唤醒工作线程
        for (int t_id = 0; t_id < THREAD_NUM; t_id++)
        {
            sem_post(&sem_workerstart[t_id]);
           /* pthread_join(handles[t_id], NULL);*/
        }

        //主线程睡眠（等待所有的工作线程完成此轮消去任务）
        for (int t_id = 0; t_id < THREAD_NUM; t_id++)
        {
            sem_wait(&sem_main);
        }

        // 主线程再次唤醒工作线程进入下一轮次的消去任务
        for (int t_id = 0; t_id < THREAD_NUM; t_id++)
        {
            sem_post(&sem_workerend[t_id]);
        }


        /* for (int i = k + 1; i < N; i++)
         {
             for (int j = k + 1; j < N; j++)
             {
                 A[i][j] = A[i][j] - A[i][k] * A[k][j];
             }
             A[i][k] = 0;
         }*/
    }
    for (int t_id = 0; t_id < THREAD_NUM; t_id++)
    {
         pthread_join(handles[t_id], NULL);
    }
    sem_destroy(&sem_main);
    for (int i = 0; i < THREAD_NUM; i++)
    {
        sem_destroy(&sem_workerstart[i]);
        sem_destroy(&sem_workerend[i]);
    }

    // end time
    QueryPerformanceCounter((LARGE_INTEGER*)&tail);
    cout << "Time:" << ((tail - head) * 1.0) / freq << "s" << endl;
    system("pause");
    return 0;
}
